package com.wasu.sdk_ott.http.live

import android.text.TextUtils
import android.util.Log
import com.wasu.constant.Config
import com.wasu.constant.SYSTEM_CATEGORY_4K_IPDVB_HUIFANG
import com.wasu.constant.SYSTEM_CATEGORY_4K_IPDVB_KANBA
import com.wasu.constant.SYSTEM_CATEGORY_4K_IPDVB_LIVE
import com.wasu.constant.SYSTEM_CATEGORY_4K_IPDVB_QIUSUO
import com.wasu.constant.TAG
import com.wasu.rxcache.RxCache
import com.wasu.rxcache.stategy.CacheStrategy

/**
 * <p>------------------------------------------------------
 * <p>Copyright (C) 2020 wasu company, All rights reserved.
 * <p>------------------------------------------------------
 * <p> 提供给外部调用接口请求类
 * <p> category 用来区分DVB模式下，直播播控，还是回放看吧求索等其他
 *
 * @author Created by zhangmz
 * @date on 2023/8/18
 */
open class IpLiveLoader(
    private val category: String? = null,
    private val baseUrl: String? = null
): BaseAttribute() {

    /**
     * 请求接口
     */
    private val service by lazy(LazyThreadSafetyMode.PUBLICATION) { IpLiveService(createDomain()) }

    /**
     * 区域编码
     */
    private val region by lazy(LazyThreadSafetyMode.PUBLICATION) { Config.getRegion() }

    /**
     * 判断是否设置测试环境，用来获得域名
     */
    override fun createDomain(): String {
        val isUseIpepgDomain = isIpepgDomain(category)
        val domain = when{
            baseUrl?.isNotEmpty() == true -> baseUrl
            isUseIpepgDomain -> getIpepgDomain()
            else -> getIpLiveDomain()
        }
        Log.v(TAG, "createDomain, category:$category; baseUrl:$baseUrl; domain:$domain")
        return domain
    }

    /**
     * 查询分组频道列表，并缓存
     */
    fun queryChannelGroupAsync(
        bIds: String? = "",
        isZip: String? = "1",
        category: String? = null,
        strategy: String? = null,
        defaultKey: String,
        success: (result: String) -> Unit = {  },
        failure: (e: Throwable) -> Unit =  {  }
    ) {
        service.queryChannelGroupAsync(
            bIds,
            isZip = isZip,
            category = category,
            if (region.isNullOrEmpty()) defaultKey else "${region}_$defaultKey",
            createStrategy(strategy),
            useIpepg = null,
            success,
            failure
        )
    }

    /**
     * 同步请求分组频道，子线程调用，其他方法策略可参考本方法处理
     * @param category 入参，区分看吧，回放，求索，直播
     * @param strategy 缓存策略
     * @see createStrategy 具体缓存策略对应关系查看
     */
    fun queryChannelGroupSync(
        bIds: String? = "",
        isZip: String? = "1",
        category: String? = null,
        strategy: String? = null,
        defaultKey: String,
        success: (result: String) -> Unit = {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        val isUseIpepg = isIpepgDomain(category)
        val param = WasuIpLiveUtils().getQueryChannelGroupParam(bIds, isZip = isZip, category = category, isUseIpepg = isUseIpepg)
        Log.v(TAG, "queryChannelGroupSync,strategy:$strategy; defaultKey:$defaultKey; param:$param")
        when(strategy){
            // 只取网络，不保存缓存
            "0" -> service.queryChannelGroupSync(bIds, isZip = isZip, category = category, param, isUseIpepg, success, failure)
            // 请求网络数据，网络数据请求成功后写入缓存
            "1" -> {
                service.queryChannelGroupSync(bIds, isZip = isZip, category = category, param, isUseIpepg,
                    success = {
                        success(it)
                        saveCache(region, defaultKey, it)
                    },
                    failure)
            }
            // 只取缓存，无网络请求
            "2" -> {
                loadCache(region, defaultKey, success, failure)
            }
            // 优先网络，当网络请求异常，无网络数据时，去加载缓存，否则不读取缓存
            "3" -> {
                service.queryChannelGroupSync(bIds, isZip = isZip, category = category, isUseIpepg = isUseIpepg,
                    success = {
                        success(it)
                        saveCache(region, defaultKey, it)
                    },
                    failure = {
                        loadCache(region, defaultKey, success, failure)
                    }
                )
            }
            // 优先缓存，当无缓存或者缓存获取异常时，再请求网络数据
            "4" -> {
                loadCache(region, defaultKey,
                    success,
                    failure = {
                        queryChannelGroupSync(bIds, isZip = isZip, category = category, "1", defaultKey, success, failure)
                    }
                )
            }
            "7" -> {
                loadCache(region, defaultKey,
                    // 有缓存，读取并回调缓存，再请求网络，刷新缓存，不回调网络数据
                    success = {
                        success(it)
                        val key = if (region.isNullOrEmpty()) defaultKey else "${region}_$defaultKey"
                        service.queryChannelGroupAsync(bIds, isZip = isZip, category = category, key, CacheStrategy.onlyRemote())
                    },
                    // 无缓存，请求网络，添加缓存，回调网络数据
                    failure = {
                        queryChannelGroupSync(bIds, isZip = isZip, category = category, "1", defaultKey, success, failure)
                    }
                )
            }
        }
    }

    /**
     * IP直播管理系统查询时移频道列表
     */
    fun queryChannelTimeShiftSync(
        isZip: String? = "1",
        success: (result: String) -> Unit,
        failure: (e: Throwable) -> Unit =  {  }
    ){
        service.queryIpLiveTimeShiftChannelSync(isZip, success, failure)
    }

    /**
     * 查询节目单列表
     */
    fun queryProgramListAsync (
        type: String,
        getType: String? = "",
        bIds: String? = "",
        bId: String? = "",
        channelId: String? = "",
        beginDate: String? = "",
        endDate: String? = "",
        isZip: String? = "1",
        category: String? = null,
        strategy: String? = null,
        defaultKey: String,
        success: (result: String) -> Unit =  {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        val isUseIpepg = isIpepgDomain(category)
        service.queryProgramListAsync(
            type, getType, bIds, bId, channelId, beginDate, endDate, isZip = isZip,
            if (region.isNullOrEmpty()) defaultKey else "${region}_$defaultKey",
            category = category,
            createStrategy(strategy),
            RxCache.getDefault(),
            isUseIpepg,
            success,
            failure
        )
    }

    /**
     * 同步请求节目单，需要子线程调用
     * type=1 单独一个key作为缓存 IPLIVE_CACHE_PROGRAM_ALLDAY_KYE
     * type=2 单独一个key作为缓存 IPLIVE_CACHE_PROGRAM_KYE
     * type=其他不做缓存
     */
    fun queryProgramListSync (
        type: String,
        getType: String? = "",
        bIds: String? = "",
        bId: String? = "",
        channelId: String? = "",
        beginDate: String? = "",
        endDate: String? = "",
        isZip: String? = "1",
        category: String? = null,
        strategy: String? = null,
        defaultKey: String,
        useIpepg: Boolean? = null,
        success: (result: String) -> Unit =  {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        val isUseIpepg = useIpepg?: isIpepgDomain(category)
        val param = WasuIpLiveUtils().getQueryProgramListParam(
            type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, isUseIpepg
        )
        Log.v(TAG, "queryProgramListSync, defaultKey:$defaultKey; param:$param")
        when(strategy){
            // 仅查询网络，不做缓存
            "0" -> {
                service.queryProgramListSync(
                    type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, param, isUseIpepg,
                    success, failure
                )
            }
            // 查询网络，并更新缓存
            "1" -> {
                service.queryProgramListSync(
                    type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, param, isUseIpepg,
                    success = {
                        success(it)
                        if (TextUtils.isEmpty(category) || SYSTEM_CATEGORY_4K_IPDVB_LIVE == category){
                            saveCache(region, defaultKey, it)
                        }
                    },
                    failure
                )
            }
            // 仅取缓存，不做网络查询
            "2" -> {
                loadCache(region, defaultKey, success, failure)
            }
            // 优先网络，当网络请求异常，无网络数据时，去加载缓存，否则不读取缓存
            "3" -> {
                service.queryProgramListSync(
                    type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, isUseIpepg = isUseIpepg,
                    success = {
                        success(it)
                        if (TextUtils.isEmpty(category) || SYSTEM_CATEGORY_4K_IPDVB_LIVE == category){
                            saveCache(region, defaultKey, it)
                        }
                    },
                    failure = {
                        loadCache(region, defaultKey, success, failure)
                    }
                )
            }
            // 优先缓存，当无缓存或者缓存获取异常时，再请求网络数据
            "4", "5" -> {
                loadCache(region, defaultKey,
                    success,
                    failure = {
                        queryProgramListSync(type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, "1", defaultKey, useIpepg, success, failure)
                    }
                )
            }
            "7" -> {
                loadCache(region, defaultKey,
                    // 有缓存，读取并回调缓存，再请求网络，刷新缓存，不回调网络数据
                    success = {
                        success(it)
                        service.queryProgramListAsync(
                            type, getType, bIds, bId, channelId, beginDate, endDate, isZip = isZip,
                            defaultKey, category = category, CacheStrategy.onlyRemote(), RxCache.getDefault(), isUseIpepg
                        )
                    },
                    // 无缓存，请求网络，添加缓存，回调网络数据
                    failure = {
                        queryProgramListSync(type, getType, bIds, bId, channelId, beginDate, endDate, isZip, category = category, "1", defaultKey, useIpepg, success, failure)
                    }
                )
            }
        }
    }

    /**
     * 根据频道id查询单个频道对象，必须子线程调用
     */
    fun queryChannelSync(
        channelId: String?,
        channelName: String? = "",
        category: String? = null,
        success: (result: String) -> Unit =  {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        // 单个频道信息的缓存，只缓存了中央一套
        val cacheDefaultKey = if (category == SYSTEM_CATEGORY_4K_IPDVB_KANBA || category == SYSTEM_CATEGORY_4K_IPDVB_HUIFANG || category == SYSTEM_CATEGORY_4K_IPDVB_QIUSUO){
            ""
        }else if ("00000000000000000000000000005210" == channelId || channelName?.contains("中央一套") == true){
            IPLIVE_CACHE_WATCHTV_CHANNEL_KYE
        } else ""
        loadCache(region, cacheDefaultKey,
            success = {
                Log.v(TAG, "loadCache queryChannelSync, result:$it")
                success(it)
            },
            failure = { e ->
                Log.e(TAG, "queryChannelSync, error:$e")
                service.queryChannelSync(channelId, channelName, category = category,
                    success = {
                        Log.v(TAG, "loadNetwork queryChannelSync, result:$it")
                        success(it)
                        // 单独保存中央一套频道信息，用于开机，看电视模式，查询频道信息快速
                        if (("00000000000000000000000000005210" == channelId || channelName?.contains("中央一套") == true) && !TextUtils.isEmpty(cacheDefaultKey)){
                            saveCache(region, IPLIVE_CACHE_WATCHTV_CHANNEL_KYE, it)
                        }
                    }, failure)
            })
    }

    /**
     * 查询频道授权列表，DVB模式
     */
    fun queryChannelAuthAsync(
        strategy: String? = null,
        defaultKey: String,
        success: (result: String) -> Unit = {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        if (!Config.isHz()){
            Log.v(TAG, "省网不支持高标清替换，所以不用调用查询授权列表接口")
            return
        }
        service.queryChannelAuthAsync(
            if (region.isNullOrEmpty()) defaultKey else "${region}_$defaultKey",
            createStrategy(strategy),
            RxCache.getDefault(),
            success,
            failure
        )
    }

    /**
     * 查询分组频道节目单版本信息
     */
    fun queryChProVersionAsync(
        type: String? = "0",
        chId: String? = "",
        success: (result: String) -> Unit =  {  },
        failure: (e: Throwable) -> Unit =  {  }
    ){
        service.queryChannelVersionAsync(
            type,
            chId,
            success,
            failure
        )
    }

}